package com.loveyukari.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.SSLContext;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.loveyukari.common.exception.InternalException;


public class HttpUtils {
    /**
     * 向服务器发送请求
     *
     * @param reqUrl
     * @param params
     * @return
     * @throws RuntimeException
     */

    public static String sendGet(String reqUrl,Map<String, Object> params,Map<String, String> headers) throws Exception {
        if (params != null){
    		Set<String> keySet = params.keySet();
    		for (String key : keySet) {
                Object value = params.get(key);
                String decode = URLEncoder.encode(value.toString(), "UTF-8");
                if (reqUrl.contains("?")){
                    reqUrl += "&";
                } else {
                    reqUrl += "?";
                }
                reqUrl = reqUrl +key+"="+decode;
    		}
    	}
        HttpGet httpGet = new HttpGet(reqUrl);
        return send(httpGet,headers);
    }

    public static String sendGet(String reqUrl,Map<String,Object> params) throws Exception {
        return sendGet(reqUrl,params,null);
    }

    public static String sendGet(String reqUrl) throws Exception {
        return sendGet(reqUrl,null,null);
    }


    public static String send(HttpUriRequest httpUriRequest,Map<String,String> headers) throws Exception {
        HttpResponse response = null;
        if (headers != null){
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                httpUriRequest.setHeader(key,value);
            }
        }
        response = HttpUtils.getHttpClient().execute(httpUriRequest);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity entity = response.getEntity();
        // 如果状态不正常
        String result = EntityUtils.toString(entity,"UTF-8");
        return result;
    }

    public static String sendPostBody(String reqUrl,String body) throws Exception {
        HttpPost httpPost = new HttpPost(reqUrl);
        StringEntity stringEntity = new StringEntity(body, "application/json", "UTF-8");
        httpPost.setEntity(stringEntity);
        return send(httpPost,null);
    }

    public static String sendPost(String reqUrl, Map<String, Object> params,Map<String,String> headers) throws Exception {
        HttpPost httpPost = new HttpPost(reqUrl);
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        if (params != null){
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                nameValuePairs.add(new BasicNameValuePair(key, String.valueOf(value)));
            }
        }
        return send(httpPost,headers);
    }

    public static String sendPost(String reqUrl,Map<String,Object> params) throws Exception {
        return sendPost(reqUrl,params,null);
    }


    private static CloseableHttpAsyncClient getAsyncClients() throws Exception {
        RegistryBuilder<SchemeIOSessionStrategy> registryBuilder = RegistryBuilder.<SchemeIOSessionStrategy>create();
        registryBuilder.register("http", NoopIOSessionStrategy.INSTANCE);
//指定信任密钥存储对象和连接套接字工厂
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        //信任任何链接
        TrustStrategy anyTrustStrategy = new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        };
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy).build();
        SSLIOSessionStrategy sslSF = new SSLIOSessionStrategy(sslContext, NoopHostnameVerifier.INSTANCE);
        registryBuilder.register("https", sslSF);
        Registry<SchemeIOSessionStrategy> registry = registryBuilder.build();
        //设置连接管理器
        PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(new DefaultConnectingIOReactor(),registry);
//      connManager.setDefaultConnectionConfig(connConfig);
//      connManager.setDefaultSocketConfig(socketConfig);
        return HttpAsyncClientBuilder.create().setConnectionManager(connManager).build();
    }

    public static CloseableHttpClient getHttpClient() throws Exception {
        RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
        ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
        registryBuilder.register("http", plainSF);
//指定信任密钥存储对象和连接套接字工厂
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        //信任任何链接
        TrustStrategy anyTrustStrategy = new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        };
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy).build();
        LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        registryBuilder.register("https", sslSF);

        Registry<ConnectionSocketFactory> registry = registryBuilder.build();
        //设置连接管理器
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
//      connManager.setDefaultConnectionConfig(connConfig);
//      connManager.setDefaultSocketConfig(socketConfig);
        //构建客户端  
        return HttpClientBuilder.create().setConnectionManager(connManager).build(); 
    }

}
